package com.hfb.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

/**
 * java SE 版 NIO ServerSocket
 *
 * 程序的问题：1、空轮训（浪费资源），效率低。（如：有十万连接中只有几个有效连接）
 *  *
 *  *  优化思路：
 *  *      事件回调——事件驱动——观察者模式
 */
public class MyNIOServer_01 {
    static List<SocketChannel> channels = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.socket().bind(new InetSocketAddress(9000));
        serverSocket.configureBlocking(false);// 设置为非阻塞
        System.out.println("服务启动成功");

        while (true) {
            // NIO的 accept 不会阻塞，内部是有OS实现的
            // 底层调用了 Linux 系统的 accept 函数
            SocketChannel socketChannel = serverSocket.accept();
            if(null != socketChannel) {
                System.out.println(socketChannel.getRemoteAddress()+"连接成功。。。");
                // 设置为非阻塞
                socketChannel.configureBlocking(false);
                channels.add(socketChannel);
            }

            channels.stream().forEach(sc->{
                ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                try {
                    int len = sc.read(byteBuffer);
                    if (len > 0) {  // 有数据 打印
                        System.out.println("接收到客户端【"+
                            sc.getRemoteAddress()+"】消息："+
                            new String(byteBuffer.array()));
                    } else if(len == -1){ // 客户端断开，移除 socket 列表
                        System.out.println("客户端【"+sc.getRemoteAddress()+"】断开连接!");
                        channels.remove(sc);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}
